/**
 * JSON-RPC 2.0 工具类
 * 提供标准的JSON-RPC 2.0协议支持
 */

export class JsonRpcClient {
  constructor(websocket = null) {
    this.websocket = websocket
    this.requestId = 0
    this.pendingRequests = new Map()
    this.methodHandlers = new Map()
    this.requestTimeout = 10000 // 默认10秒超时
  }

  /**
   * 设置WebSocket连接
   * @param {WebSocket} websocket WebSocket实例
   */
  setWebSocket(websocket) {
    this.websocket = websocket
  }

  /**
   * 设置请求超时时间
   * @param {number} timeout 超时时间(毫秒)
   */
  setRequestTimeout(timeout) {
    this.requestTimeout = timeout
  }

  /**
   * 创建RPC请求消息
   * @param {string} method 方法名
   * @param {any} params 参数
   * @returns {object} RPC请求对象
   */
  createRequest(method, params) {
    const id = ++this.requestId
    return {
      jsonrpc: "2.0",
      method: method,
      params: params,
      id: id
    }
  }

  /**
   * 创建RPC通知消息
   * @param {string} method 方法名
   * @param {any} params 参数
   * @returns {object} RPC通知对象
   */
  createNotification(method, params) {
    return {
      jsonrpc: "2.0",
      method: method,
      params: params
    }
  }

  /**
   * 创建RPC响应消息
   * @param {number} id 请求ID
   * @param {any} result 结果
   * @param {object} error 错误对象
   * @returns {object} RPC响应对象
   */
  createResponse(id, result, error = null) {
    const response = {
      jsonrpc: "2.0",
      id: id
    }
    
    if (error) {
      response.error = error
    } else {
      response.result = result
    }
    
    return response
  }

  /**
   * 发送RPC请求（期望响应）
   * @param {string} method 方法名
   * @param {any} params 参数
   * @returns {Promise} Promise对象
   */
  sendRequest(method, params) {
    return new Promise((resolve, reject) => {
      if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
        reject(new Error('WebSocket is not connected'))
        return
      }

      const request = this.createRequest(method, params)
      
      // 存储请求回调
      this.pendingRequests.set(request.id, { resolve, reject })
      
      // 设置超时
      setTimeout(() => {
        if (this.pendingRequests.has(request.id)) {
          this.pendingRequests.delete(request.id)
          reject(new Error(`RPC request timeout: ${method}`))
        }
      }, this.requestTimeout)
      
      this.sendMessage(request)
    })
  }

  /**
   * 发送RPC通知（不期望响应）
   * @param {string} method 方法名
   * @param {any} params 参数
   */
  sendNotification(method, params) {
    if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
      console.warn('WebSocket is not connected, cannot send notification')
      return
    }

    const notification = this.createNotification(method, params)
    this.sendMessage(notification)
  }

  /**
   * 发送RPC响应
   * @param {number} id 请求ID
   * @param {any} result 结果
   * @param {object} error 错误对象
   */
  sendResponse(id, result, error = null) {
    if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
      console.warn('WebSocket is not connected, cannot send response')
      return
    }

    const response = this.createResponse(id, result, error)
    this.sendMessage(response)
  }

  /**
   * 注册方法处理器
   * @param {string} method 方法名
   * @param {function} handler 处理函数
   */
  registerMethod(method, handler) {
    this.methodHandlers.set(method, handler)
  }

  /**
   * 取消注册方法处理器
   * @param {string} method 方法名
   */
  unregisterMethod(method) {
    this.methodHandlers.delete(method)
  }

  /**
   * 处理接收到的RPC消息
   * @param {object} message RPC消息对象
   */
  async handleMessage(message) {
    try {
      // 检查是否为有效的JSON-RPC 2.0消息
      if (message.jsonrpc !== "2.0") {
        console.warn('Invalid JSON-RPC version:', message)
        return
      }

      // 处理响应
      if (message.hasOwnProperty('result') || message.hasOwnProperty('error')) {
        this.handleResponse(message)
        return
      }

      // 处理方法调用或通知
      if (message.method) {
        await this.handleMethodCall(message)
      }

    } catch (err) {
      console.error('Error handling RPC message:', err)
      if (message.id) {
        this.sendResponse(message.id, null, {
          code: -32603,
          message: 'Internal error',
          data: err.message
        })
      }
    }
  }

  /**
   * 处理RPC响应
   * @param {object} message 响应消息
   */
  handleResponse(message) {
    const pending = this.pendingRequests.get(message.id)
    if (pending) {
      this.pendingRequests.delete(message.id)
      if (message.error) {
        pending.reject(new Error(message.error.message || 'RPC Error'))
      } else {
        pending.resolve(message.result)
      }
    }
  }

  /**
   * 处理RPC方法调用
   * @param {object} message 方法调用消息
   */
  async handleMethodCall(message) {
    const { method, params, id } = message

    try {
      const handler = this.methodHandlers.get(method)
      
      if (!handler) {
        console.warn('Unknown RPC method:', method)
        if (id) {
          this.sendResponse(id, null, {
            code: -32601,
            message: 'Method not found',
            data: method
          })
        }
        return
      }

      // 调用处理器
      const result = await handler(params)
      
      // 如果有ID，发送响应（方法调用），否则是通知
      if (id) {
        this.sendResponse(id, result)
      }

    } catch (err) {
      console.error(`Error handling RPC method ${method}:`, err)
      if (id) {
        this.sendResponse(id, null, {
          code: -32603,
          message: 'Internal error',
          data: err.message
        })
      }
    }
  }

  /**
   * 发送消息到WebSocket
   * @param {object} message 消息对象
   */
  sendMessage(message) {
    if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
      this.websocket.send(JSON.stringify(message))
    } else {
      console.warn('WebSocket is not connected, cannot send message:', message)
    }
  }

  /**
   * 清理所有待处理的请求
   * @param {string} reason 清理原因
   */
  cleanup(reason = 'Client cleanup') {
    // 清理所有待处理的RPC请求
    this.pendingRequests.forEach(({ reject }) => {
      reject(new Error(reason))
    })
    this.pendingRequests.clear()
    
    // 清理方法处理器
    this.methodHandlers.clear()
  }

  /**
   * 获取待处理请求数量
   * @returns {number} 待处理请求数量
   */
  getPendingRequestCount() {
    return this.pendingRequests.size
  }

  /**
   * 获取已注册的方法列表
   * @returns {string[]} 方法名列表
   */
  getRegisteredMethods() {
    return Array.from(this.methodHandlers.keys())
  }
}

// 默认导出
export default JsonRpcClient

// 便捷的创建函数
export function createJsonRpcClient(websocket = null) {
  return new JsonRpcClient(websocket)
}

// 常用的错误代码常量
export const RPC_ERROR_CODES = {
  PARSE_ERROR: -32700,
  INVALID_REQUEST: -32600,
  METHOD_NOT_FOUND: -32601,
  INVALID_PARAMS: -32602,
  INTERNAL_ERROR: -32603
} 